package eu.robico.simulator.simulatorinterface;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

import eu.robico.simulator.simulatorinterface.RobotStatus.RobotStatusUpdate;
import eu.robico.simulator.simulatorinterface.SimulatorStatus.SimulatorStatusUpdate;
import eu.robico.simulator.simulatorinterface.actionpanel.ActionPanel;
import eu.robico.simulator.simulatorinterface.communication.Protocol.Trigger;

public class ApplicationWindow implements Observer
{
	MainController controller;
	ExecutorService executor;
	
	private JFrame frmRobicoSimulator;
	private JTextField txtConnection;
	private JTextField textStatus;
	private JTextField textLeftWheel;
	private JTextField textRightWheel;
	private JTextField txtLed1;
	private JTextField textLED2;
	private JTextField textBuzzer;
	private JTextField textHostIp;
	private JTextField textHostPort;
	private JTextField txtWheelControl;
	
	private JButton btnProximity;
	private JButton btnEmergency;
	private JButton btnBackCollision;
	private JButton btnFrontCollision;
	private JButton btnConnect;
	private JButton btnDisconnect;
	private JLabel lblWheelControl;
	private JToggleButton tglbtnColorlaneLeft;
	private JToggleButton tglbtnColorlaneRight;
	private JPanel manualControlsPanel;
	private JPanel panel;
	
	private ActionPanel actionPanel;
	
	
	private boolean connected;
	private JPanel mainPanel;
	private JPanel connectionPanel;
	private JPanel robotStatusPanel;
	private JPanel sensorButtonPanel;
	private JToggleButton tglbtnSideExitLeft;
	private JToggleButton tglbtnSideExitRight;

	/**
	 * Create the application.
	 */
	public ApplicationWindow(MainController controller) 
	{
		this.executor = Executors.newSingleThreadExecutor();
		initialize();
		this.controller = controller;
		controller.setApplicationWindow(this);
	}

	/**
	 * Set the window to visible visibility 
	 */
	void setVisibility(boolean bool)
	{
		frmRobicoSimulator.setVisible(bool);
	}
	
	private void connect()
	{
		//Get IP
		final String ip;
		if (textHostIp.getText().length() == 0)
			ip = "127.0.0.1";
		else if (textHostIp.getText().length() < 7)
		{
			txtConnection.setText("Invalid IP");
			txtConnection.setForeground(Color.red);
			return;
		}
		else
			ip = textHostIp.getText();
		
		//Get PORT
		final short port;
		if (textHostPort.getText().length() == 0)
			port = 12345;
		else try
		{
			port = Short.parseShort(textHostPort.getText());
		}
		catch (NumberFormatException e)
		{
			txtConnection.setText("Invalid port");
			txtConnection.setForeground(Color.red);
			return;
		}
		
		//Connect
		txtConnection.setText("Attempting connection...");
		txtConnection.setForeground(Color.black);
		executor.execute(new Runnable()
		{
			public void run()
			{
				controller.connect(ip, port);
			}
		});
	}
	
	private void connected()
	{
		btnEmergency.setEnabled(true);
		btnProximity.setEnabled(true);
		btnBackCollision.setEnabled(true);
		btnFrontCollision.setEnabled(true);
		tglbtnColorlaneLeft.setEnabled(true);
		tglbtnColorlaneRight.setEnabled(true);
		tglbtnSideExitLeft.setEnabled(true);
		tglbtnSideExitRight.setEnabled(true);
		btnDisconnect.setEnabled(true);
		btnConnect.setEnabled(false);
		txtWheelControl.setEnabled(true);
		textBuzzer.setEnabled(true);
		textLED2.setEnabled(true);
		textLeftWheel.setEnabled(true);
		textRightWheel.setEnabled(true);
		textStatus.setEnabled(true);
		textStatus.setText("Working");
		txtLed1.setEnabled(true);
		textHostIp.setEditable(false);
		textHostPort.setEditable(false);
	}
	
	private void disconnect()
	{
		txtConnection.setText("Attempting disconnect...");
		executor.execute(new Runnable()
		{
			public void run()
			{
				controller.disconnect();
			}
		});
	}
	
	private void disconnected()
	{
		btnEmergency.setEnabled(false);
		btnProximity.setEnabled(false);
		btnBackCollision.setEnabled(false);
		btnFrontCollision.setEnabled(false);
		tglbtnColorlaneLeft.setEnabled(false);
		tglbtnColorlaneLeft.setSelected(false);
		tglbtnColorlaneRight.setEnabled(false);
		tglbtnColorlaneRight.setSelected(false);
		tglbtnSideExitLeft.setEnabled(false);
		tglbtnSideExitLeft.setSelected(false);
		tglbtnSideExitRight.setEnabled(false);
		tglbtnSideExitRight.setSelected(false);
		btnDisconnect.setEnabled(false);
		btnConnect.setEnabled(true);
		txtWheelControl.setEnabled(false);
		txtWheelControl.setText("");
		textBuzzer.setEnabled(false);
		textBuzzer.setText("");
		textLED2.setEnabled(false);
		textLED2.setText("");
		textLeftWheel.setEnabled(false);
		textLeftWheel.setText("");
		textRightWheel.setEnabled(false);
		textRightWheel.setText("");
		textStatus.setEnabled(false);
		textStatus.setText("");
		txtLed1.setEnabled(false);
		txtLed1.setText("");
		textHostIp.setEditable(true);
		textHostPort.setEditable(true);
		
		actionPanel.stopSimulation();
	}
	
	private void sendTrigger(final Trigger trigger)
	{
		executor.execute(new Runnable()
		{
			public void run()
			{
				controller.sendTrigger(trigger);
			}
		});
	}
	
	void updateRobotStatus(final RobotStatus robotStatus, final RobotStatusUpdate type)
	{
		SwingUtilities.invokeLater(new Runnable() 
		{
			public void run()
			{
				switch (type)
				{
				case BUZZERUPDATE:
					textBuzzer.setText(componentStatusToString(robotStatus.getBuzzer()));
					break;
				case LED1UPDATE:
					txtLed1.setText(componentStatusToString(robotStatus.getLed1()));
					break;
				case LED2UPDATE:
					textLED2.setText(componentStatusToString(robotStatus.getLed2()));
					break;
				case LEFTCOLORLANESENSORUPDATE:
					tglbtnColorlaneLeft.setSelected(robotStatus.getColorLaneLeftSensor());
					break;
				case LEFTWHEELUPDATE:
					if (robotStatus.hasLeftWheelValue())
						textLeftWheel.setText(robotStatus.getLeftWheelStatusString());
					else
						textLeftWheel.setText("");
					break;
				case RIGHTCOLORLANESENSORUPDATE:
					tglbtnColorlaneRight.setSelected(robotStatus.getColorLaneRightSensor());
					break;
				case RIGHTWHEELUPDATE:
					if (robotStatus.hasRightWheelValue())
						textRightWheel.setText(robotStatus.getRightWheelStatusString());
					else
						textRightWheel.setText("");
					break;
				case SLEEPUPDATE:
					//TODO: implement this
					break;
				case WHEELCONTROLUPDATE:
					txtWheelControl.setText(componentStatusToString(robotStatus.getWheelControl()));
					break;
				case LEFTSIDEEXITSENSORUPDATE:
					tglbtnSideExitLeft.setSelected(robotStatus.getLeftSideExitSensor());
					break;
				case RIGHTSIDEEXITSENSORUPDATE:
					tglbtnSideExitRight.setSelected(robotStatus.getRightSideExitSensor());
					break;
				}
			}
		});
	}
	
	void updateSimulatorStatus(final SimulatorStatus simulatorStatus, final SimulatorStatusUpdate type)
	{
		SwingUtilities.invokeLater(new Runnable() 
		{
			public void run()
			{
				switch (type)
				{
				case CONNECTIONSTATEUPDATE:
					switch (simulatorStatus.getConnectionState())
					{
					case CONNECTED:
					case DISCONNECTED:
						txtConnection.setForeground(Color.black);
						break;
					case ERROR:
						txtConnection.setForeground(Color.red);
						break;
					}
					if (connected && simulatorStatus.getConnectionState() != SimulatorStatus.ConnectionState.CONNECTED)
					{
						connected = false;
						disconnected();
					}
					else if (!connected && simulatorStatus.getConnectionState() == SimulatorStatus.ConnectionState.CONNECTED)
					{
						connected = true;
						connected();
					}
					break;
				case CONNECTIONSTATUSUPDATE:
					if (simulatorStatus.hasConnectionStatus())
						txtConnection.setText(simulatorStatus.getConnectionStatus());
					else
						txtConnection.setText("");
					break;
				case IPUPDATE:
					if (simulatorStatus.hasIp())
						textHostIp.setText(simulatorStatus.getIp());
					else
						textHostIp.setText("");
					break;
				case PORTUPDATE:
					textHostPort.setText(simulatorStatus.getPort() + "");
					break;
					//TODO: fix this
//				case SIMULATORSTATUSUPDATE:
//					if (simulatorStatus.hasSimulatorStatus())
//						textStatus.setText(simulatorStatus.getSimulatorStatus());
//					else
//						textStatus.setText("");
//					break;
				}
				//Simulator Status
				
				//Connection Status
				
				//Connection State
				
				
			}
		});
	}
	
	private String componentStatusToString(boolean bool)
	{
		String status = (bool) ? "on" : "off";
		return status;
	}
	
	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmRobicoSimulator = new JFrame();
		frmRobicoSimulator.setIconImage(Toolkit.getDefaultToolkit().getImage(ApplicationWindow.class.getResource("/com/sun/java/swing/plaf/windows/icons/Computer.gif")));
		frmRobicoSimulator.setResizable(false);
		frmRobicoSimulator.setTitle("Robico Prototype Simulator v1.0");
		frmRobicoSimulator.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmRobicoSimulator.getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		
		mainPanel = new JPanel();
		frmRobicoSimulator.getContentPane().add(mainPanel);
		GridBagLayout gbl_mainPanel = new GridBagLayout();
		gbl_mainPanel.columnWidths = new int[]{0, 0};
		gbl_mainPanel.rowHeights = new int[]{0, 0, 0, 0, 0};
		gbl_mainPanel.columnWeights = new double[]{1.0, 1.0};
		gbl_mainPanel.rowWeights = new double[]{0.0, 0.0, 1.0, 1.0, Double.MIN_VALUE};
		mainPanel.setLayout(gbl_mainPanel);

		
		actionPanel = new ActionPanel();
		panel = actionPanel;
		panel.setPreferredSize(new Dimension(910, 425));
		GridBagConstraints gbc_actionPanel = new GridBagConstraints();
		gbc_actionPanel.gridwidth = 2;
		gbc_actionPanel.gridy = 0;
		gbc_actionPanel.gridx = 0;
		mainPanel.add(actionPanel, gbc_actionPanel);
		
		
		manualControlsPanel = new JPanel();
		manualControlsPanel.setBorder(new TitledBorder(new CompoundBorder(new BevelBorder(BevelBorder.RAISED, new Color(240, 240, 240), new Color(255, 255, 255), new Color(105, 105, 105), new Color(160, 160, 160)), new LineBorder(new Color(180, 180, 180), 5)), "Sensorcontrols", TitledBorder.CENTER, TitledBorder.TOP, null, null));
		manualControlsPanel.setLayout(new BoxLayout(manualControlsPanel, BoxLayout.PAGE_AXIS));
		
		
		GridBagConstraints gbc_manualControlsPanel = new GridBagConstraints();
		gbc_manualControlsPanel.gridwidth = 2;
		gbc_manualControlsPanel.fill = GridBagConstraints.HORIZONTAL;
		gbc_manualControlsPanel.insets = new Insets(0, 0, 5, 0);
		gbc_manualControlsPanel.gridx = 0;
		gbc_manualControlsPanel.gridy = 3;
		mainPanel.add(manualControlsPanel, gbc_manualControlsPanel);
		
		sensorButtonPanel = new JPanel();
		manualControlsPanel.add(sensorButtonPanel);
		
		btnProximity = new JButton("Proximity");
		sensorButtonPanel.add(btnProximity);
		btnProximity.setEnabled(false);
		btnProximity.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				sendTrigger(Trigger.PROXIMITYSIGNAL);
			}
		});
		
		btnEmergency = new JButton("Emergency");
		sensorButtonPanel.add(btnEmergency);
		btnEmergency.setAlignmentX(Component.RIGHT_ALIGNMENT);
		btnEmergency.setEnabled(false);
		
		btnFrontCollision = new JButton("Collision Front");
		sensorButtonPanel.add(btnFrontCollision);
		btnFrontCollision.setEnabled(false);
		
		btnBackCollision = new JButton("Collision Back");
		sensorButtonPanel.add(btnBackCollision);
		btnBackCollision.setEnabled(false);
		btnBackCollision.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				sendTrigger(Trigger.COLLISIONBACKSIGNAL);
			}
		});
		
		tglbtnColorlaneLeft = new JToggleButton("Colorlane Left");
		sensorButtonPanel.add(tglbtnColorlaneLeft);
		tglbtnColorlaneLeft.setEnabled(false);
		
		tglbtnColorlaneRight = new JToggleButton("Colorlane Right");
		sensorButtonPanel.add(tglbtnColorlaneRight);
		tglbtnColorlaneRight.setEnabled(false);
		
		tglbtnSideExitLeft = new JToggleButton("Side-exit Left");
		tglbtnSideExitLeft.setEnabled(false);
		sensorButtonPanel.add(tglbtnSideExitLeft);
		
		tglbtnSideExitRight = new JToggleButton("Side-exit Right");
		tglbtnSideExitRight.setEnabled(false);
		sensorButtonPanel.add(tglbtnSideExitRight);
		tglbtnColorlaneRight.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				sendTrigger(Trigger.COLORLANERIGHTTOGGLE);
			}
		});
		tglbtnColorlaneLeft.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				sendTrigger(Trigger.COLORLANELEFTTOGGLE);
			}
		});
		btnFrontCollision.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				sendTrigger(Trigger.COLLISIONFRONTSIGNAL);
			}
		});
		btnEmergency.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				sendTrigger(Trigger.EMERGENCYSIGNAL);
			}
		});
		
		connectionPanel = new JPanel();
		connectionPanel.setBorder(new TitledBorder(new CompoundBorder(new BevelBorder(BevelBorder.RAISED, new Color(240, 240, 240), new Color(255, 255, 255), new Color(105, 105, 105), new Color(160, 160, 160)), new LineBorder(new Color(180, 180, 180), 5)), "Connection", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		GridBagConstraints gbc_connectionPanel = new GridBagConstraints();
		gbc_connectionPanel.fill = GridBagConstraints.BOTH;
		gbc_connectionPanel.gridx = 0;
		gbc_connectionPanel.gridy = 1;
		mainPanel.add(connectionPanel, gbc_connectionPanel);
		GridBagLayout gbl_connectionPanel = new GridBagLayout();
		gbl_connectionPanel.columnWidths = new int[]{0, 0};
		gbl_connectionPanel.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
		gbl_connectionPanel.columnWeights = new double[]{1, 1};
		gbl_connectionPanel.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
		connectionPanel.setLayout(gbl_connectionPanel);
		
		JLabel lblConnectionStatus = new JLabel("Connection status:");
		GridBagConstraints gbc_lblConnectionStatus = new GridBagConstraints();
		gbc_lblConnectionStatus.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblConnectionStatus.anchor = GridBagConstraints.WEST;
		gbc_lblConnectionStatus.insets = new Insets(0, 0, 5, 5);
		gbc_lblConnectionStatus.gridx = 0;
		gbc_lblConnectionStatus.gridy = 1;
		connectionPanel.add(lblConnectionStatus, gbc_lblConnectionStatus);
		
		txtConnection = new JTextField();
		GridBagConstraints gbc_txtConnection = new GridBagConstraints();
		gbc_txtConnection.insets = new Insets(0, 0, 5, 0);
		gbc_txtConnection.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtConnection.gridx = 1;
		gbc_txtConnection.gridy = 1;
		connectionPanel.add(txtConnection, gbc_txtConnection);
		txtConnection.setText("Disconnected");
		txtConnection.setHorizontalAlignment(SwingConstants.RIGHT);
		txtConnection.setEditable(false);
		txtConnection.setColumns(5);
		
		JLabel lblSimulatorStatus = new JLabel("Simulator status:");
		GridBagConstraints gbc_lblSimulatorStatus = new GridBagConstraints();
		gbc_lblSimulatorStatus.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblSimulatorStatus.anchor = GridBagConstraints.WEST;
		gbc_lblSimulatorStatus.insets = new Insets(0, 0, 5, 5);
		gbc_lblSimulatorStatus.gridx = 0;
		gbc_lblSimulatorStatus.gridy = 2;
		connectionPanel.add(lblSimulatorStatus, gbc_lblSimulatorStatus);
		lblSimulatorStatus.setHorizontalAlignment(SwingConstants.LEFT);
		
		JLabel lblHostIp = new JLabel("Host IP:");
		GridBagConstraints gbc_lblHostIp = new GridBagConstraints();
		gbc_lblHostIp.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblHostIp.anchor = GridBagConstraints.WEST;
		gbc_lblHostIp.insets = new Insets(0, 0, 5, 5);
		gbc_lblHostIp.gridx = 0;
		gbc_lblHostIp.gridy = 3;
		connectionPanel.add(lblHostIp, gbc_lblHostIp);
		
		JLabel lblHostPort = new JLabel("Host PORT:");
		GridBagConstraints gbc_lblHostPort = new GridBagConstraints();
		gbc_lblHostPort.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblHostPort.anchor = GridBagConstraints.WEST;
		gbc_lblHostPort.insets = new Insets(0, 0, 5, 5);
		gbc_lblHostPort.gridx = 0;
		gbc_lblHostPort.gridy = 4;
		connectionPanel.add(lblHostPort, gbc_lblHostPort);
		
		textStatus = new JTextField();
		GridBagConstraints gbc_textStatus = new GridBagConstraints();
		gbc_textStatus.insets = new Insets(0, 0, 5, 0);
		gbc_textStatus.fill = GridBagConstraints.HORIZONTAL;
		gbc_textStatus.gridx = 1;
		gbc_textStatus.gridy = 2;
		connectionPanel.add(textStatus, gbc_textStatus);
		textStatus.setHorizontalAlignment(SwingConstants.RIGHT);
		textStatus.setText("Disconnected");
		textStatus.setEditable(false);
		textStatus.setEnabled(false);
		textStatus.setColumns(5);
		
		textHostIp = new JTextField();
		textHostIp.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_textHostIp = new GridBagConstraints();
		gbc_textHostIp.insets = new Insets(0, 0, 5, 0);
		gbc_textHostIp.fill = GridBagConstraints.HORIZONTAL;
		gbc_textHostIp.gridx = 1;
		gbc_textHostIp.gridy = 3;
		connectionPanel.add(textHostIp, gbc_textHostIp);
		textHostIp.setColumns(10);
		
		textHostPort = new JTextField();
		textHostPort.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_textHostPort = new GridBagConstraints();
		gbc_textHostPort.insets = new Insets(0, 0, 5, 0);
		gbc_textHostPort.fill = GridBagConstraints.HORIZONTAL;
		gbc_textHostPort.gridx = 1;
		gbc_textHostPort.gridy = 4;
		connectionPanel.add(textHostPort, gbc_textHostPort);
		textHostPort.setColumns(10);
		
		btnConnect = new JButton("Connect");
		GridBagConstraints gbc_btnConnect = new GridBagConstraints();
		gbc_btnConnect.insets = new Insets(15, 0, 0, 0);
		gbc_btnConnect.gridx = 0;
		gbc_btnConnect.gridy = 6;
		connectionPanel.add(btnConnect, gbc_btnConnect);
		btnConnect.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				connect();
			}
		});
		
		btnDisconnect = new JButton("Disconnect");
		GridBagConstraints gbc_btnDisconnect = new GridBagConstraints();
		gbc_btnDisconnect.insets = new Insets(15, 0, 0, 0);
		gbc_btnDisconnect.gridx = 1;
		gbc_btnDisconnect.gridy = 6;
		connectionPanel.add(btnDisconnect, gbc_btnDisconnect);
		btnDisconnect.setEnabled(false);
		
		robotStatusPanel = new JPanel();
		robotStatusPanel.setBorder(new TitledBorder(new CompoundBorder(new BevelBorder(BevelBorder.RAISED, new Color(240, 240, 240), new Color(255, 255, 255), new Color(105, 105, 105), new Color(160, 160, 160)), new LineBorder(new Color(180, 180, 180), 5)), "Robotstatus", TitledBorder.RIGHT, TitledBorder.TOP, null, null));
		GridBagConstraints gbc_robotStatusPanel = new GridBagConstraints();
		gbc_robotStatusPanel.fill = GridBagConstraints.BOTH;
		gbc_robotStatusPanel.gridx = 1;
		gbc_robotStatusPanel.gridy = 1;
		mainPanel.add(robotStatusPanel, gbc_robotStatusPanel);
		GridBagLayout gbl_robotStatusPanel = new GridBagLayout();
		gbl_robotStatusPanel.columnWidths = new int[]{0, 0};
		gbl_robotStatusPanel.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0};
		gbl_robotStatusPanel.columnWeights = new double[]{5, 5};
		gbl_robotStatusPanel.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
		robotStatusPanel.setLayout(gbl_robotStatusPanel);
		
		lblWheelControl = new JLabel("Wheel Control:");
		GridBagConstraints gbc_lblWheelControl = new GridBagConstraints();
		gbc_lblWheelControl.anchor = GridBagConstraints.WEST;
		gbc_lblWheelControl.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblWheelControl.insets = new Insets(0, 0, 5, 5);
		gbc_lblWheelControl.gridx = 0;
		gbc_lblWheelControl.gridy = 1;
		robotStatusPanel.add(lblWheelControl, gbc_lblWheelControl);
		
		JLabel lblLeftWheel = new JLabel("Left Wheel:");
		GridBagConstraints gbc_lblLeftWheel = new GridBagConstraints();
		gbc_lblLeftWheel.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblLeftWheel.anchor = GridBagConstraints.WEST;
		gbc_lblLeftWheel.insets = new Insets(0, 0, 5, 5);
		gbc_lblLeftWheel.gridx = 0;
		gbc_lblLeftWheel.gridy = 2;
		robotStatusPanel.add(lblLeftWheel, gbc_lblLeftWheel);
		
		JLabel lblRightWheel = new JLabel("Right Wheel:");
		GridBagConstraints gbc_lblRightWheel = new GridBagConstraints();
		gbc_lblRightWheel.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblRightWheel.anchor = GridBagConstraints.WEST;
		gbc_lblRightWheel.insets = new Insets(0, 0, 5, 5);
		gbc_lblRightWheel.gridx = 0;
		gbc_lblRightWheel.gridy = 3;
		robotStatusPanel.add(lblRightWheel, gbc_lblRightWheel);
		
		JLabel lblLed_1 = new JLabel("Led1:");
		GridBagConstraints gbc_lblLed_1 = new GridBagConstraints();
		gbc_lblLed_1.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblLed_1.anchor = GridBagConstraints.WEST;
		gbc_lblLed_1.insets = new Insets(0, 0, 5, 5);
		gbc_lblLed_1.gridx = 0;
		gbc_lblLed_1.gridy = 4;
		robotStatusPanel.add(lblLed_1, gbc_lblLed_1);
		
		JLabel lblLed = new JLabel("Led2:");
		GridBagConstraints gbc_lblLed = new GridBagConstraints();
		gbc_lblLed.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblLed.anchor = GridBagConstraints.WEST;
		gbc_lblLed.insets = new Insets(0, 0, 5, 5);
		gbc_lblLed.gridx = 0;
		gbc_lblLed.gridy = 5;
		robotStatusPanel.add(lblLed, gbc_lblLed);
		
		JLabel lblBuzzer = new JLabel("Buzzer:");
		GridBagConstraints gbc_lblBuzzer = new GridBagConstraints();
		gbc_lblBuzzer.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblBuzzer.anchor = GridBagConstraints.WEST;
		gbc_lblBuzzer.insets = new Insets(0, 0, 5, 5);
		gbc_lblBuzzer.gridx = 0;
		gbc_lblBuzzer.gridy = 6;
		robotStatusPanel.add(lblBuzzer, gbc_lblBuzzer);
		
		txtWheelControl = new JTextField();
		txtWheelControl.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_txtWheelControl = new GridBagConstraints();
		gbc_txtWheelControl.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtWheelControl.insets = new Insets(0, 0, 5, 0);
		gbc_txtWheelControl.gridx = 1;
		gbc_txtWheelControl.gridy = 1;
		robotStatusPanel.add(txtWheelControl, gbc_txtWheelControl);
		txtWheelControl.setEditable(false);
		txtWheelControl.setEnabled(false);
		txtWheelControl.setColumns(10);
		
		textLeftWheel = new JTextField();
		textLeftWheel.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_textLeftWheel = new GridBagConstraints();
		gbc_textLeftWheel.fill = GridBagConstraints.HORIZONTAL;
		gbc_textLeftWheel.insets = new Insets(0, 0, 5, 0);
		gbc_textLeftWheel.gridx = 1;
		gbc_textLeftWheel.gridy = 2;
		robotStatusPanel.add(textLeftWheel, gbc_textLeftWheel);
		textLeftWheel.setEnabled(false);
		textLeftWheel.setEditable(false);
		textLeftWheel.setColumns(10);
		
		textRightWheel = new JTextField();
		textRightWheel.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_textRightWheel = new GridBagConstraints();
		gbc_textRightWheel.fill = GridBagConstraints.HORIZONTAL;
		gbc_textRightWheel.insets = new Insets(0, 0, 5, 0);
		gbc_textRightWheel.gridx = 1;
		gbc_textRightWheel.gridy = 3;
		robotStatusPanel.add(textRightWheel, gbc_textRightWheel);
		textRightWheel.setEnabled(false);
		textRightWheel.setEditable(false);
		textRightWheel.setColumns(10);
		
		txtLed1 = new JTextField();
		txtLed1.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_txtLed1 = new GridBagConstraints();
		gbc_txtLed1.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtLed1.insets = new Insets(0, 0, 5, 0);
		gbc_txtLed1.gridx = 1;
		gbc_txtLed1.gridy = 4;
		robotStatusPanel.add(txtLed1, gbc_txtLed1);
		txtLed1.setEnabled(false);
		txtLed1.setEditable(false);
		txtLed1.setColumns(10);
		
		textLED2 = new JTextField();
		textLED2.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_textLED2 = new GridBagConstraints();
		gbc_textLED2.fill = GridBagConstraints.HORIZONTAL;
		gbc_textLED2.insets = new Insets(0, 0, 5, 0);
		gbc_textLED2.gridx = 1;
		gbc_textLED2.gridy = 5;
		robotStatusPanel.add(textLED2, gbc_textLED2);
		textLED2.setEnabled(false);
		textLED2.setEditable(false);
		textLED2.setColumns(10);
		
		textBuzzer = new JTextField();
		textBuzzer.setHorizontalAlignment(SwingConstants.RIGHT);
		GridBagConstraints gbc_textBuzzer = new GridBagConstraints();
		gbc_textBuzzer.fill = GridBagConstraints.HORIZONTAL;
		gbc_textBuzzer.insets = new Insets(0, 0, 5, 0);
		gbc_textBuzzer.gridx = 1;
		gbc_textBuzzer.gridy = 6;
		robotStatusPanel.add(textBuzzer, gbc_textBuzzer);
		textBuzzer.setEnabled(false);
		textBuzzer.setEditable(false);
		textBuzzer.setColumns(10);
		btnDisconnect.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				disconnect();
			}
		});
		frmRobicoSimulator.pack();
		frmRobicoSimulator.setLocationRelativeTo(null);
	}

	@Override
	public void update(Observable arg0, Object arg1) 
	{
		if (arg0 instanceof SimulatorStatus)
			updateSimulatorStatus((SimulatorStatus) arg0, (SimulatorStatusUpdate) arg1);
		else if (arg0 instanceof RobotStatus)
			updateRobotStatus((RobotStatus) arg0, (RobotStatusUpdate) arg1);
	}

}
